package channelHandler

import (
	"errors"
	"gitee.com/fierce_wolf/go-fox-edge-channel-common/channelLogger"
	"gitee.com/fierce_wolf/go-fox-edge-common/commLogger"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Hex"
	"github.com/dop251/goja"
	"go-fox-edge-channel-tcp-server/channelEngine/channelManager"
	"go-fox-edge-channel-tcp-server/channelEngine/handler/SessionHandler"
	"go-fox-edge-channel-tcp-server/channelEngine/handler/manageHandler"
	"go-fox-edge-channel-tcp-server/channelEngine/scriptEngine"
	"net"
)

type ChannelNotify struct {
	Notify         *OperateEntityNotify
	Format         string
	SessionHandler sessionHandler.SessionHandler
	ManageHandler  manageHandler.ManageHandler
}

func (e *ChannelNotify) getServiceKey(pack []byte) (string, error) {
	manufacturer := e.Notify.OperateEntity.Manufacturer
	deviceType := e.Notify.OperateEntity.DeviceType
	operateName := e.Notify.OperateEntity.OperateName

	engine := scriptEngine.GetScriptEngine(manufacturer, deviceType, operateName)

	// 执行JSP脚本中的函数：getHeaderLength
	encode, ok := goja.AssertFunction(engine.Get("getServiceKey"))
	if !ok {
		return "", errors.New("未定义函数：getServiceKey")
	}

	data := ""
	if e.Notify.Format == "TXT" {
		data = string(pack)
	} else {
		data = Hex.EncodeToString(pack)
	}

	// 执行函数
	res, err := encode(goja.Undefined(), engine.ToValue(data))
	if err != nil {
		return "", err
	}

	return res.String(), nil
}

func (e *ChannelNotify) ChannelActive(conn net.Conn) {
	channelManager.Insert(conn)
	commLogger.Info("连接建立: 远端设备->" + conn.RemoteAddr().String())
}

func (e *ChannelNotify) ChannelRead(conn net.Conn, data []byte) {
	if e.Notify == nil {
		return
	}

	// 检查：channel是否已经标识上了信息
	serviceKey := channelManager.GetServiceKeyByRemoteAddr(conn.RemoteAddr().String())
	if serviceKey == "" {
		// 从报文总获得业务特征信息
		key, err := e.getServiceKey(data)
		if err != nil {
			channelLogger.PrintlInfoLogger("身份识别:" + conn.RemoteAddr().String() + "; 识别出错->" + err.Error())
			return
		}
		if key == "" {
			channelLogger.PrintlInfoLogger("身份识别:" + conn.RemoteAddr().String() + "; 识别出错->" + "ID为空")
			return
		}

		// 标记:serviceKey信息
		serviceKey = key
		channelManager.SetServiceKey(conn, serviceKey)

		// 记录接收到的报文
		channelLogger.PrintlInfoLogger("身份识别:" + conn.RemoteAddr().String() + "; serviceKey->" + serviceKey)

		// 发出创建通道的消息
		e.ManageHandler.CreateChannel(serviceKey)
		// 发出创建设备的消息
		e.ManageHandler.CreateDevice(serviceKey)
	}

	// 消息处理
	e.SessionHandler.OnMessage(conn, serviceKey, data)
}

func (e *ChannelNotify) ChannelClose(conn net.Conn) {
	commLogger.Info("连接断开: 远端设备->" + conn.RemoteAddr().String())

	channelManager.RemoveByRemoteAddr(conn.RemoteAddr().String())
}

func (e *ChannelNotify) ExceptionCaught(conn net.Conn, err error) {
	commLogger.Info("数据异常: 远端设备->" + conn.RemoteAddr().String() + ", 错误信息->" + err.Error())
}
